/*
//
//                  INTEL CORPORATION PROPRIETARY INFORMATION
//     This software is supplied under the terms of a license agreement or
//     nondisclosure agreement with Intel Corporation and may not be copied
//     or disclosed except in accordance with the terms of that agreement.
//          Copyright(c) 2003-2007 Intel Corporation. All Rights Reserved.
//
//     Intel(R) Integrated Performance Primitives AAC Decode Sample for Windows*
//
//  By downloading and installing this sample, you hereby agree that the
//  accompanying Materials are being provided to you under the terms and
//  conditions of the End User License Agreement for the Intel(R) Integrated
//  Performance Primitives product previously accepted by you. Please refer
//  to the file ippEULA.rtf or ippEULA.txt located in the root directory of your Intel(R) IPP
//  product installation for more information.
//
//  MPEG-4 and AAC are international standards promoted by ISO, IEC, ITU, ETSI
//  and other organizations. Implementations of these standards, or the standard
//  enabled platforms may require licenses from various entities, including
//  Intel Corporation.
//
*/

#include "umc_defs.h"

#if defined (UMC_ENABLE_AAC_INT_AUDIO_DECODER)

#include "aac_dec_int.h"
#include "aac_dec_own.h"
#include "aac_dec_own_int.h"

/********************************************************************/

static Ipp32s is_intensity(s_SE_Individual_channel_stream *pData,
                           Ipp32s group,
                           Ipp32s sfb);

static Ipp32s is_noise(s_SE_Individual_channel_stream *pData,
                       Ipp32s group,
                       Ipp32s sfb);

/********************************************************************/

Ipp32s aacidec_ics_apply_scale_factors(s_SE_Individual_channel_stream *pData,
                                       Ipp32s *p_spectrum)
{
  Ipp32s  g;
  Ipp32s  w_num;

  if (pData->window_sequence != EIGHT_SHORT_SEQUENCE) {
    ippsPow43Scale_16s32s_Sf(pData->spectrum_data, p_spectrum, pData->sf[0],
                             pData->sfb_offset_long_window,
                             SF_OFFSET, pData->max_sfb, 1, -2);

    ippsZero_32s(p_spectrum + pData->sfb_offset_long_window[pData->max_sfb],
                 1024 - pData->sfb_offset_long_window[pData->max_sfb]);
  } else {
    Ipp16s *ptr = pData->spectrum_data;
    for (g = 0; g < pData->num_window_groups; g++) {
      w_num = pData->len_window_group[g];

      ippsPow43Scale_16s32s_Sf(ptr, p_spectrum, pData->sf[g],
                               pData->sfb_offset_short_window,
                               SF_OFFSET, pData->max_sfb, w_num, -5);
      p_spectrum +=
        w_num * pData->sfb_offset_short_window[pData->max_sfb];

      ptr +=
        w_num * pData->sfb_offset_short_window[pData->max_sfb];
    }
  }

  return 0;
}

/********************************************************************/

Ipp32s aacidec_cpe_apply_ms(sCpe_channel_element *pElement,
                            Ipp32s *l_spec,
                            Ipp32s *r_spec)
{
  Ipp32s i, g, sfb;
  Ipp32s tmp;
  Ipp32s *sfb_offset;
  Ipp32s num_window_groups = pElement->streams[0].num_window_groups;
  Ipp32s max_sfb = pElement->streams[0].max_sfb;
  s_SE_Individual_channel_stream *p_ics_right;

  p_ics_right = &pElement->streams[1];

  sfb_offset =
    pElement->streams[0].window_sequence == EIGHT_SHORT_SEQUENCE ?
    pElement->streams[0].sfb_offset_short_window :
    pElement->streams[0].sfb_offset_long_window;

  if (pElement->ms_mask_present >= 1) {
    for (g = 0; g < num_window_groups; g++) {
      Ipp32s len_window_group = pElement->streams[0].len_window_group[g];
      for (sfb = 0; sfb < max_sfb; sfb++) {
        if ((pElement->ms_used[g][sfb] || pElement->ms_mask_present == 2) &&
            !is_intensity(p_ics_right, g, sfb) &&
            !is_noise(p_ics_right, g, sfb)) {
          for (i = sfb_offset[sfb] * len_window_group;
               i < sfb_offset[sfb + 1]  * len_window_group; i++) {
            tmp = l_spec[i] - r_spec[i];
            l_spec[i] = l_spec[i] + r_spec[i];
            r_spec[i] = tmp;
          }
        }
      }
      l_spec += sfb_offset[max_sfb] * len_window_group;
      r_spec += sfb_offset[max_sfb] * len_window_group;
    }
  }
  return 0;
}

/********************************************************************/

static Ipp32s invert_intensity(sCpe_channel_element *pElement,
                               Ipp32s group,
                               Ipp32s sfb)
{
  if (pElement->ms_mask_present == 1)
    return (1 - 2 * pElement->ms_used[group][sfb]);
  return 1;
}

/********************************************************************/

static Ipp32s pow2table[] = {1073741824, 1276901417, 1518500250, 1805811301};

/********************************************************************/

Ipp32s aacidec_cpe_apply_intensity(sCpe_channel_element *pElement,
                                   Ipp32s *l_spec,
                                   Ipp32s *r_spec)
{
  Ipp32s i, g, sfb;
  Ipp32s group;
  Ipp32s *sfb_offset;
  Ipp32s num_window_groups;
  Ipp32s max_sfb;
  s_SE_Individual_channel_stream *p_ics_right;

  p_ics_right = &pElement->streams[1];

  sfb_offset =
    pElement->streams[0].window_sequence == EIGHT_SHORT_SEQUENCE ?
    pElement->streams[0].sfb_offset_short_window :
    pElement->streams[0].sfb_offset_long_window;

  num_window_groups = p_ics_right->num_window_groups;
  max_sfb = p_ics_right->max_sfb;

  group = 0;
  for (g = 0; g < num_window_groups; g++) {
    Ipp32s len_window_group = p_ics_right->len_window_group[g];
    for (sfb = 0; sfb < max_sfb; sfb++) {
      Ipp32s tmp0 = is_intensity(p_ics_right, g, sfb);
      if (tmp0) {
        Ipp32s tmp1 = invert_intensity(pElement, g, sfb);
        Ipp32s itmp = -p_ics_right->sf[g][sfb];
        Ipp32s exp = 30 - (itmp >> 2);
        Ipp32s mant = pow2table[itmp & 3];

        tmp0 = tmp0 * tmp1;
        mant = mant * tmp0;
        if (exp > 63) exp = 63;

        for (i = sfb_offset[sfb] * len_window_group;
             i < sfb_offset[sfb + 1]  * len_window_group; i++) {
          r_spec[i] = (Ipp32s)(((Ipp64s)l_spec[i] * mant) >> exp);
        }
      }
    }
    l_spec += sfb_offset[max_sfb] * len_window_group;
    r_spec += sfb_offset[max_sfb] * len_window_group;
  }

  return 0;
}

/********************************************************************/

static Ipp32s is_intensity(s_SE_Individual_channel_stream *pData,
                           Ipp32s group,
                           Ipp32s sfb)
{
  switch (pData->sfb_cb[group][sfb]) {
  case INTENSITY_HCB:
    return 1;
  case INTENSITY_HCB2:
    return -1;
  default:
    return 0;
  }
}

/********************************************************************/

static Ipp32s is_noise(s_SE_Individual_channel_stream *pData,
                       Ipp32s group,
                       Ipp32s sfb)
{
  if (pData->sfb_cb[group][sfb] == NOISE_HCB)
    return 1;
  return 0;
}

/********************************************************************/

static void noise_generator(Ipp32s *dst,
                            Ipp32s len,
                            Ipp32s *noiseState,
                            Ipp32s *norm,
                            Ipp32s *scale)
{
  Ipp64s norml, ltemp;
  Ipp32s normi;
  Ipp32s seed, i;
  Ipp32s shift;

  norml = 0;
  seed = *noiseState;

  if (len == 1) shift = 0;
  else {
    Ipp32s tmp = len - 1;
    shift = -1;
    while (tmp > 0) {
      shift++;
      tmp >>= 1;
    }
  }
  for (i = 0; i < len; i++) {
    seed = (1664525L * seed) + 1013904223L;
    dst[i] = (Ipp32s)seed;
    norml += ((Ipp64s)seed * seed) >> shift;
  }
  *noiseState = seed;
  normi = (Ipp32s)(norml >> 32);

  while (normi < 1073741824) {
    shift--;
    normi <<= 1;
  }

  ltemp  = ((Ipp64s)normi * normi ) >> 32; /* Q30 */
  ltemp  = ltemp * 13563;                  /* Q44 */
  ltemp -= (Ipp64s)normi * 16760;          /* Q44 */
  ltemp += 39107824713728L;                /* Q44 */
  normi  = (Ipp32s)(ltemp >> 14);          /* Q30 */
  shift += (30 * 2 + 31 + 32);
  if (shift & 1) {
    normi = (Ipp32s)(((Ipp64s)normi * 1518500250) >> 31);
    shift--;
  }

  *scale = shift >> 1;
  *norm = normi;
}

/********************************************************************/

Ipp32s aacidec_apply_pns(s_SE_Individual_channel_stream *pDataL,
                         s_SE_Individual_channel_stream *pDataR,
                         Ipp32s *p_spectrumL,
                         Ipp32s *p_spectrumR,
                         Ipp32s numCh,
                         Ipp32s ms_mask_present,
                         Ipp32s ms_used[8][49],
                         Ipp32s *noiseState)
{
  Ipp32s  i, g, sfb, ich;
  Ipp32s  norm;
  Ipp32s  normScale;
  Ipp32s  *sfb_offset;
  Ipp32s  num_window_groups, max_sfb;
  s_SE_Individual_channel_stream *pData = pDataL;
  Ipp32s  *p_spectrum = p_spectrumL;
  Ipp32s  *p_spectrum_l = p_spectrumL;


  for (ich = 0; ich < numCh; ich++) {

    sfb_offset = pData->window_sequence == EIGHT_SHORT_SEQUENCE ?
      pData->sfb_offset_short_window : pData->sfb_offset_long_window;

    num_window_groups = pData->num_window_groups;
    max_sfb = pData->max_sfb;

    for (g = 0; g < num_window_groups; g++) {
      Ipp32s len_window_group = pData->len_window_group[g];
      for (sfb = 0; sfb < max_sfb; sfb++) {
        if (pData->sfb_cb[g][sfb] == NOISE_HCB) {
          Ipp32s tmp = 0;
          if ((ich == 1) && (ms_mask_present >= 1)) {
            if ((ms_used[g][sfb] != 0) || (ms_mask_present == 2)) {
              tmp = 1;
            }
          }

          if (tmp) {
            Ipp32s itmp = pData->sf[g][sfb] - pDataL->sf[g][sfb];
            Ipp32s exp = 30 - (itmp >> 2);
            Ipp32s mant = pow2table[itmp & 3];

            if (exp > 0) {
              if (exp > 63) exp = 63;

              for (i = sfb_offset[sfb] * len_window_group;
                   i < sfb_offset[sfb + 1]  * len_window_group; i++) {
                p_spectrum[i] = (Ipp32s)(((Ipp64s)p_spectrum_l[i] * mant) >> exp);
              }
            } else {
              for (i = sfb_offset[sfb] * len_window_group;
                   i < sfb_offset[sfb + 1]  * len_window_group; i++) {
                p_spectrum[i] = (Ipp32s)(((Ipp64s)p_spectrum_l[i] * mant) << exp);
              }
            }
          } else {
            Ipp32s itmp = pData->sf[g][sfb];
            Ipp32s exp;
            Ipp32s mant = pow2table[itmp & 3];

            noise_generator(p_spectrum + sfb_offset[sfb] * len_window_group,
                            (sfb_offset[sfb + 1] - sfb_offset[sfb]) * len_window_group,
                            noiseState, &norm, &normScale);

            mant = (Ipp32s)(((Ipp64s)norm * mant) >> 30);
            exp = normScale - (itmp >> 2);

            if (exp > 0) {
              if (exp > 63) exp = 63;

              for (i = sfb_offset[sfb] * len_window_group;
                   i < sfb_offset[sfb + 1]  * len_window_group; i++) {
                p_spectrum[i] = (Ipp32s)(((Ipp64s)p_spectrum[i] * mant) >> exp);
              }
            } else {
              for (i = sfb_offset[sfb] * len_window_group;
                   i < sfb_offset[sfb + 1]  * len_window_group; i++) {
                p_spectrum[i] = (Ipp32s)(((Ipp64s)p_spectrum[i] * mant) << exp);
              }
            }
          }
        }
      }
      p_spectrum += sfb_offset[max_sfb] * len_window_group;
      p_spectrum_l += sfb_offset[max_sfb] * len_window_group;
    }

    pData = pDataR;
    p_spectrum = p_spectrumR;
    p_spectrum_l = p_spectrumL;
  }

  return 0;
}

/********************************************************************/

Ipp32s aacidec_deinterlieve(s_SE_Individual_channel_stream *pData,
                            Ipp32s *p_spectrum)
{
  if ((pData->window_sequence == EIGHT_SHORT_SEQUENCE)) {
    Ipp32s *sfb_offset = pData->sfb_offset_short_window;
    Ipp32s num_window_groups = pData->num_window_groups;
    Ipp32s max_sfb = pData->max_sfb;
    Ipp32s buf[1024];
    Ipp32s *pBuf = buf;
    Ipp32s g, sfb, b;

    ippsCopy_32s(p_spectrum, buf, 1024);

    for (g = 0; g < num_window_groups; g++) {
      Ipp32s len_window_group = pData->len_window_group[g];
      Ipp32s offset = 0;
      for (sfb = 0; sfb < max_sfb; sfb++) {
        Ipp32s len = sfb_offset[sfb + 1] - sfb_offset[sfb];
        for (b = 0; b < len_window_group; b++) {
          ippsCopy_32s(pBuf, p_spectrum + b * 128 + offset, (Ipp16s)len);
          pBuf += len;
        }
        offset += len;

        for (b = 0; b < len_window_group; b++) {
          ippsZero_32s(p_spectrum + b * 128 + offset, 128 - offset);
        }
      }
      p_spectrum += 128*len_window_group;
    }
  }
  return 0;
}

/********************************************************************/

Ipp32s aacidec_gain_table[4][8] = {
{ 1073741824, 1170923776, 1276901376, 1392470912,
  1518500224, 1655936256, 1805811328, 1969251200 },
{ 1073741824, 1276901376, 1518500224, 1805811328, 0, 0, 0, 0},
{ 1073741824, 1518500224, 0, 0, 0, 0, 0, 0},
{ 1073741824, 0, 0, 0, 0, 0, 0, 0}
};

/********************************************************************/

void aacidec_coupling_gain_calculation(sCoupling_channel_element *pElement,
                                       sCoupling_channel_data *pData,
                                       Ipp32s cc_gain[18][MAX_GROUP_NUMBER][MAX_SFB],
                                       Ipp32s cc_gain_factor[18][MAX_GROUP_NUMBER][MAX_SFB])
{
  Ipp32s *pgain_table = aacidec_gain_table[pData->gain_element_scale];
  Ipp32s shift = (3 - pData->gain_element_scale);
  Ipp32s ch = 0;
  Ipp32s c, g, sfb;

  for (c = 0; c < pData->num_gain_element_lists; c++) {
    if (pData->cge[c]) {
      Ipp32s fac = -pElement->cc_fact[c][0][0];
      Ipp32s ifac = fac >> shift;
      Ipp32s scale = pgain_table[fac - (ifac << shift)];

      for (g = 0; g < pElement->stream.num_window_groups; g++) {
        for (sfb = 0; sfb < pElement->stream.max_sfb; sfb++) {
          if (pElement->stream.sfb_cb[g][sfb] != ZERO_HCB) {
            cc_gain[ch][g][sfb] = scale;
            cc_gain_factor[ch][g][sfb] = ifac - 30;
          } else {
            cc_gain[ch][g][sfb] = 0;
            cc_gain_factor[ch][g][sfb] = 0;
          }
        }
      }
    } else {
      if (pData->gain_element_sign) {
        for (g = 0; g < pElement->stream.num_window_groups; g++) {
          for (sfb = 0; sfb < pElement->stream.max_sfb; sfb++) {
            if (pElement->stream.sfb_cb[g][sfb] != ZERO_HCB) {
              Ipp32s sign = pElement->cc_fact[c][g][sfb] & 1;
              Ipp32s fac = -(pElement->cc_fact[c][g][sfb] >> 1);
              Ipp32s ifac = fac >> shift;
              Ipp32s scale = pgain_table[fac - (ifac << shift)];

              if (sign) scale = -scale;
              cc_gain[ch][g][sfb] = scale;
              cc_gain_factor[ch][g][sfb] = ifac - 30;
            } else {
              cc_gain[ch][g][sfb] = 0;
              cc_gain_factor[ch][g][sfb] = 0;
            }
          }
        }
      } else {
        for (g = 0; g < pElement->stream.num_window_groups; g++) {
          for (sfb = 0; sfb < pElement->stream.max_sfb; sfb++) {
            if (pElement->stream.sfb_cb[g][sfb] != ZERO_HCB) {
              Ipp32s fac = -(pElement->cc_fact[c][g][sfb]);
              Ipp32s ifac = fac >> shift;
              Ipp32s scale = pgain_table[fac - (ifac << shift)];
              cc_gain[ch][g][sfb] = scale;
              cc_gain_factor[ch][g][sfb] = ifac - 30;
            } else {
              cc_gain[ch][g][sfb] = 0;
              cc_gain_factor[ch][g][sfb] = 0;
            }
          }
        }
      }
    }

    if (pData->cc_lr[c] == 3) {
      ch++;
    } else {
      ch += 2;
    }
  }
}

/********************************************************************/

void aacidec_coupling_spectrum(AACDec *state,
                               sCoupling_channel_data *pData,
                               Ipp32s *c_spectrum,
                               Ipp32s curr_win_sequence,
                               Ipp32s cc_gain[18][MAX_GROUP_NUMBER][MAX_SFB],
                               Ipp32s cc_gain_factor[18][MAX_GROUP_NUMBER][MAX_SFB])
{
  Ipp32s *m_spectrum, *pc_spectrum;
  Ipp32s c, ch, g, m_ch, sfb, w;
  Ipp32s *sfb_offset = pData->sfb_offset;
  Ipp32s max_sfb = pData->max_sfb;
  Ipp32s num_window_groups = pData->num_window_groups;
  Ipp32s num_el = 0;
  Ipp32s tmp[1024];
  Ipp32s target_win_sequence, scalef;

  ch = 0;

  for (c = 0; c < pData->num_coupled_elements + 1; c++) {
    m_ch = pData->cc_target_ch[c];
    if (m_ch < 0) continue;

    /* if cpe and only right channel */
    if ((pData->cc_target_id[c]) && (pData->cc_lr[num_el] == 1))
      m_ch++;

    target_win_sequence = state->com.m_curr_win_sequence[m_ch];
    scalef = 0;
    if ((target_win_sequence == EIGHT_SHORT_SEQUENCE) &&
        (curr_win_sequence != EIGHT_SHORT_SEQUENCE)) {
      scalef = -3;
    } else if ((target_win_sequence != EIGHT_SHORT_SEQUENCE) &&
               (curr_win_sequence == EIGHT_SHORT_SEQUENCE)) {
      scalef = 3;
    }

    m_spectrum = state->m_spectrum_data[m_ch];
    pc_spectrum = c_spectrum;
    for (g = 0; g < num_window_groups; g++) {
      Ipp32s len_window_group = pData->len_window_group[g];
      for (w = 0; w < len_window_group; w++) {
        for (sfb = 0; sfb < max_sfb; sfb++) {
          Ipp32s len = sfb_offset[sfb + 1] - sfb_offset[sfb];
          ippsMulC_32s_Sfs(pc_spectrum + sfb_offset[sfb], cc_gain[ch][g][sfb],
                           tmp, len, scalef - cc_gain_factor[ch][g][sfb]);
          ippsAdd_32s_ISfs(tmp, m_spectrum + sfb_offset[sfb], len, 0);
        }
        m_spectrum += 128;
        pc_spectrum += 128;
      }
    }

    if (pData->cc_target_id[c]) { /* if cpe */
      if (pData->cc_lr[num_el] == 3) {

        target_win_sequence = state->com.m_curr_win_sequence[m_ch+1];
        scalef = 0;
        if ((target_win_sequence == EIGHT_SHORT_SEQUENCE) &&
            (curr_win_sequence != EIGHT_SHORT_SEQUENCE)) {
          scalef = -3;
        } else if ((target_win_sequence != EIGHT_SHORT_SEQUENCE) &&
                  (curr_win_sequence == EIGHT_SHORT_SEQUENCE)) {
          scalef = 3;
        }

        m_spectrum = state->m_spectrum_data[m_ch+1];
        pc_spectrum = c_spectrum;
        for (g = 0; g < num_window_groups; g++) {
          Ipp32s len_window_group = pData->len_window_group[g];
          for (w = 0; w < len_window_group; w++) {
            for (sfb = 0; sfb < max_sfb; sfb++) {
              Ipp32s len = sfb_offset[sfb + 1] - sfb_offset[sfb];
              ippsMulC_32s_Sfs(pc_spectrum + sfb_offset[sfb], cc_gain[ch+1][g][sfb],
                               tmp, len, scalef - cc_gain_factor[ch+1][g][sfb]);
              ippsAdd_32s_ISfs(tmp, m_spectrum + sfb_offset[sfb], len, 0);
            }
            m_spectrum += 128;
            pc_spectrum += 128;
          }
        }
        num_el++;
      } else if (pData->cc_lr[num_el] == 0) {

        target_win_sequence = state->com.m_curr_win_sequence[m_ch+1];
        scalef = 0;
        if ((target_win_sequence == EIGHT_SHORT_SEQUENCE) &&
            (curr_win_sequence != EIGHT_SHORT_SEQUENCE)) {
          scalef = -3;
        } else if ((target_win_sequence != EIGHT_SHORT_SEQUENCE) &&
                  (curr_win_sequence == EIGHT_SHORT_SEQUENCE)) {
          scalef = 3;
        }

        m_spectrum = state->m_spectrum_data[m_ch+1];
        pc_spectrum = c_spectrum;
        for (g = 0; g < num_window_groups; g++) {
          Ipp32s len_window_group = pData->len_window_group[g];
          for (w = 0; w < len_window_group; w++) {
            for (sfb = 0; sfb < max_sfb; sfb++) {
              Ipp32s len = sfb_offset[sfb + 1] - sfb_offset[sfb];
              ippsMulC_32s_Sfs(pc_spectrum + sfb_offset[sfb], cc_gain[ch][g][sfb],
                               tmp, len, scalef - cc_gain_factor[ch][g][sfb]);
              ippsAdd_32s_ISfs(tmp, m_spectrum + sfb_offset[sfb], len, 0);
            }
            m_spectrum += 128;
            pc_spectrum += 128;
          }
        }
      }
    }
    ch += 2;
    num_el++;
  }
}

/********************************************************************/

void aacidec_coupling_samples(AACDec *state,
                              sCoupling_channel_data *pData,
                              Ipp32s *c_samlpes,
                              Ipp32s cc_gain[18][MAX_GROUP_NUMBER][MAX_SFB],
                              Ipp32s cc_gain_factor[18][MAX_GROUP_NUMBER][MAX_SFB])
{
  Ipp32s c, ch, m_ch;
  Ipp32s num_el = 0;
  Ipp32s tmp[1024];

  ch = 0;

  for (c = 0; c < pData->num_coupled_elements + 1; c++) {
    m_ch = pData->cc_target_ch[c];
    if (m_ch < 0) continue;

    /* if cpe and only right channel */
    if ((pData->cc_target_id[c]) && (pData->cc_lr[num_el] == 1))
      m_ch++;

    ippsMulC_32s_Sfs(c_samlpes, cc_gain[ch][0][0],
                     tmp, 1024, -cc_gain_factor[ch][0][0]);
    ippsAdd_32s_ISfs(tmp, state->m_spectrum_data[m_ch], 1024, 0);

    if (pData->cc_target_id[c]) { /* if cpe */
      if (pData->cc_lr[num_el] == 3) {
        ippsMulC_32s_Sfs(c_samlpes, cc_gain[ch+1][0][0],
                         tmp, 1024, -cc_gain_factor[ch+1][0][0]);
        ippsAdd_32s_ISfs(tmp, state->m_spectrum_data[m_ch+1], 1024, 0);
        num_el++;
      } else if (pData->cc_lr[num_el] == 0) {
        ippsMulC_32s_Sfs(c_samlpes, cc_gain[ch][0][0],
                         tmp, 1024, -cc_gain_factor[ch][0][0]);
        ippsAdd_32s_ISfs(tmp, state->m_spectrum_data[m_ch+1], 1024, 0);
      }
    }
    ch += 2;
    num_el++;
  }
}

/********************************************************************/

#endif //UMC_ENABLE_AAC_INT_AUDIO_DECODER

